package objects;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

/**
 * Klasa prostokata
 * @author yoman
 *
 */
public class Rectangle {
	/**
	 * Precyzja do obliczania wierzcholkow
	 */
	private final static int PRECISION = 5;
	/**
	 * Precyzja do sprawdzania punktow
	 */
	private final static int POINTPRECISION = 15;
	/**
	 * Minimalna dlugosc boku
	 */
	private final static int MINLENGTH = 10;
	/**
	 * Precyzja dlugosci odchylenia
	 */
	private final static int SIDEPRECISION = 5;
	
	/**
	 * Licznik obiektow
	 */
	public static int counter = 0;

	/**
	 * Sprawdzenie czy podana tablica punktow jest prostokatem
	 *
	 * @return boolean
	 */
	public static boolean isRectangle(ArrayList<Point> points) {
		int amountPoints = points.size();//ilosc par punktow
		double length1,length2,length3,length4;
		double diagonalLength1,diagonalLength2; //dlugosc przekatnych
		int badPoints = 0;
		Point p1,p2,p3,p4; //sprawdzenie
		Line l1,l2,l3,l4; //boki
		Line diagonal1,diagonal2; //przekatne
		
		
		p1 = getPointMinX(points);
		p2 = getPointMinY(points);		
		p3 = getPointMaxX(points);		
		p4 = getPointMaxY(points);
		
		l1 = new Line(p1,p2);
		l2 = new Line(p2,p3);	
		l3 = new Line(p3,p4);	
		l4 = new Line(p4,p1);
		
		diagonal1 = new Line(p1,p3);
		diagonal2 = new Line(p2,p4);
		
		length1 = l1.getLength();
		length2 = l2.getLength();
		length3 = l3.getLength();
		length4 = l4.getLength();
		
		diagonalLength1 = diagonal1.getLength();
		diagonalLength2 = diagonal2.getLength();
		
		if(!(Line.diagonalIsEqual(diagonalLength1,diagonalLength2) && 
				Line.lineLengthIsEqual(length1,length3)  &&
				Line.lineLengthIsEqual(length2,length4)   &&
				length1>MINLENGTH && length2>MINLENGTH &&
				length3>MINLENGTH && length4>MINLENGTH)) {
			return false;
		}
		
//		String filename= "/home/yoman/Obrazy/findObject/points/points"+counter++ +".png";
//		drawRectangle(l1, l2, l3, l4, filename,1024,724);
		int pointprecision = (int) Math.floor((length1 + length2 + length3 + length4)/8);
		for (int i=0;i<amountPoints;i++) {
			Point p = points.get(i);
			if(p.x+POINTPRECISION >= l1.x1 && p.y-POINTPRECISION<=l1.y1 
					&& p.x -POINTPRECISION<= l1.x2 && p.y+POINTPRECISION>=l1.y2 && 
					l1.isPointOnLine(p) &&
					checkLength(p, l1)) {
					continue;				
				
			} else if(p.x +POINTPRECISION>= l2.x1 && p.y+POINTPRECISION>=l2.y1 && 
					p.x -POINTPRECISION<= l2.x2 && p.y -POINTPRECISION<=l2.y2 && 
					l2.isPointOnLine(p) && checkLength(p, l2)) {
				continue;
			} else if(p.x-POINTPRECISION <= l3.x1 && p.y+POINTPRECISION>=l3.y1 && 
					p.x+POINTPRECISION >= l3.x2 && p.y-POINTPRECISION<=l3.y2 && 
					l3.isPointOnLine(p)  && checkLength(p, l3)) {
				continue;
			} else if(p.x-POINTPRECISION <= l4.x1 && p.y-POINTPRECISION<=l4.y1 && 
					p.x+POINTPRECISION >= l4.x2 && p.y+POINTPRECISION>=l4.y2 && 
					l4.isPointOnLine(p)  && checkLength(p, l4)) {
				continue;
			} else {
//				System.out.println("x ="  + p.x + "y =" + p.y);
//				System.out.println("x ="  + p.x + "y =" + p.y);
				return false;
							
			}
		//	System.out.println("blednych " + badPoints);
		}
		
//		System.out.println("diag1 =" + diagonalLength1);
//		System.out.println("diag2 =" + diagonalLength2);
		return true;
	}
	
	/**
	 * max X, max Y
	 * @return
	 */
	public static Point getPointMaxX(ArrayList<Point> points){
		Point maxPoint = points.get(0);
		int max = maxPoint.getX();
		for (int i = 1; i<points.size(); i++) {
			Point currentPoint = points.get(i);

			if( (currentPoint.getX()+PRECISION>=max) && currentPoint.getY() > maxPoint.y) {
				max = currentPoint.getX();
				maxPoint = points.get(i);
			} else if (currentPoint.getX()>max) {
				if(currentPoint.getY() +PRECISION> maxPoint.y) {
					max = currentPoint.getX();
					maxPoint = points.get(i);
				}

			} 
		}
		return maxPoint;
	}
	
	/**
	 * Max Y, min x
	 * 
	 * @return
	 */
	public static Point getPointMaxY(ArrayList<Point> points){
		Point point = points.get(0);
		int max = point.getY();
		for(int i = 1; i<points.size(); i++){
			Point currentPoint = points.get(i);
			if(currentPoint.getY()>max) {
				point = currentPoint;
				max = point.getY();
			} else if( (currentPoint.getX()+PRECISION>=max) && currentPoint.getX() < point.x) {
				max = currentPoint.getY();
				point = points.get(i);
			}
		}
		return point;
	}
	
	/**
	 * Min Y, Max X 
	 * @return
	 */
	public static Point getPointMinY(ArrayList<Point> points){
		Point minPoint = points.get(0);
		Point minPointY = points.get(0);
		int min = minPoint.getY();
		for (int i = 1; i<points.size(); i++){
			Point currentPoint = points.get(i);			 
			 if(currentPoint.getY()<min) {
				    minPointY = currentPoint;
					min = minPoint.getY();
			}
			 
				
			if( (currentPoint.getY()-PRECISION <= min) && currentPoint.getX() > minPointY.x -10) {
					minPoint = currentPoint;
			}
		}

		return minPoint;
	}
	
	/**
	 * min X min Y
	 * @return
	 */
	public static Point getPointMinX(ArrayList<Point> points){
		Point minPoint = points.get(0);
		
		Point minPointX = points.get(0);
		int min = minPoint.getX();
		for(int i = 1; i<points.size(); i++){
			Point currentPoint = points.get(i);			 
			 if(currentPoint.getX()<min) {
				 	minPointX = currentPoint;
					min = minPoint.getX();
			}
			 
				
			if( (currentPoint.getX()-PRECISION <= min) && currentPoint.getY() < minPointX.y -10) {
					minPoint = currentPoint;
			} 
		}
		
		return minPoint;
	}
	
	/**
	 * Rysowanie prostokata
	 * 
	 * @param l1
	 * @param l2
	 * @param l3
	 * @param l4
	 */
	public static void drawRectangle(Line l1, Line l2, Line l3, Line l4, String filename, int width, int height) {
	    File file = new File(filename);
	    BufferedImage image2 = new BufferedImage(1024,724,6);
		image2.createGraphics().drawLine(l1.x1, l1.y1, l1.x2, l1.y2);
		image2.createGraphics().drawLine(l2.x1, l2.y1, l2.x2, l2.y2);
		image2.createGraphics().drawLine(l3.x1, l3.y1, l3.x2, l3.y2);
		image2.createGraphics().drawLine(l4.x1, l4.y1, l4.x2, l4.y2);

		try {
			javax.imageio.ImageIO.write(image2, "png", file);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public static boolean checkLength(Point p, Line l1) {
		Double lengthToP1 = new Line(p, l1.p1).getLength();
		Double lengthToP2 = new Line(p, l1.p2).getLength();
		Double overallLength = lengthToP1 + lengthToP2 - SIDEPRECISION;
		if( overallLength > l1.getLength() ) {
//			System.out.println("dlugosc " + overallLength);
//			System.out.println("dlugosc l1 " + l1.getLength());
			return false;
		}
		return true;
	}
	

}
